// 简单模拟物理跳跃
// g++ jumpSDL.cpp -o jumpSDL.out -std=c++11 -lSDL2 -lSDL2_image
// 空格键启动
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <iostream>
#include <ctime>
#define WIN_WIDTH 400
#define WIN_HEIGHT 300
#define G 9.80

class Vector2D {
public:
float x, y;
Vector2D() {}
//Vector2D(float tx, float ty) : x(tx), y(ty) {}
Vector2D(float tx, float ty) {
    x = tx;
    y = ty;
}
// 向量复制
Vector2D(const Vector2D &a) : x(a.x), y(a.y) {}
// 向量相加
Vector2D operator+(Vector2D a) {
    return Vector2D(x+a.x, y+a.y);
}
// 标量乘积
Vector2D operator*(float dt) {
    return Vector2D(dt*x, dt*y);
}
};


class Man {
private:
const int width = 50;
const int height = 50;
Vector2D position = Vector2D(0.0f, (float)(WIN_HEIGHT - height));
Vector2D velocity = Vector2D(10.0f, -60.0f);
Vector2D gravity = Vector2D(0.0f, 10.0f);

public:
SDL_Rect shape = {(int)(position.x+0.5), (int)(position.y+0.5), width, height};

public:
Vector2D changeStatus(float dt) {
    // 核心公式
    position = position + velocity*dt;
    velocity = velocity + gravity*dt;
    shape.x = (int)position.x;
    shape.y = (int)position.y;
}
// 地面和墙壁的碰撞
void onGrand() {
    if ((int)(shape.y + shape.h) > WIN_HEIGHT) {
        shape.y = WIN_HEIGHT - shape.h;
        position.y = (float)(shape.y + 0.5);
        velocity.y = -60.0f;
    }
    if ((int)(shape.x + shape.w) > WIN_WIDTH) {
        shape.x = WIN_WIDTH - shape.w;
        velocity.x = -velocity.x;
    }
    if((int)(shape.x) < 0) {
        shape.x = 0;
        velocity.x = -velocity.x;
    }
}
};




int main(int argc, char** argv) {
    SDL_Window* gWindow;
    SDL_Renderer* render;
    SDL_Texture* texture;
    SDL_Surface* surface;
    SDL_Rect texRect = {80, 140, 45, 35};
    SDL_Init(SDL_INIT_EVERYTHING);
    printf("%d\n", IMG_Init(IMG_INIT_PNG));
    gWindow = SDL_CreateWindow("jump!jump!jump!", 
                    SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 
                    WIN_WIDTH, WIN_HEIGHT, 
                    SDL_WINDOW_SHOWN);
    render = SDL_CreateRenderer(gWindow, -1, 0);
    surface = IMG_Load("./pics/flyingMario.png");
    SDL_SetColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 255, 255, 255));
    texture = SDL_CreateTextureFromSurface(render, surface);
    SDL_SetRenderDrawBlendMode(render, SDL_BLENDMODE_BLEND);
    SDL_SetRenderDrawColor(render, 0,0,0,255);

    Man man;
    bool jumping = false;
    
    // 锁定帧率<=60
    int fps = 60.0f;
    const int64_t delta_time = (int64_t) roundf(1000.0f / 60.0f);
    int64_t render_timer = (int64_t) roundf(1000.0f / (float)fps);

    SDL_Event event;
    bool quit = false;
    while (!quit) {
        const int64_t begin_frame_time = (int64_t) SDL_GetTicks();
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                std::cout << "goodBye!" << std::endl;
                quit = true;
            }
            if (event.type == SDL_KEYDOWN) {
                if (event.key.keysym.sym == SDLK_SPACE) {
                    jumping = !jumping;
                }
            }
        }
        if (jumping) {
            man.changeStatus(0.15f);
            man.onGrand();                
        }
        render_timer -= delta_time;
        if (render_timer <= 0) {
            SDL_SetRenderDrawColor(render, 0, 0, 0, 255);
            SDL_RenderClear(render);
            SDL_SetRenderDrawColor(render, 255, 255, 255, 255);
            SDL_RenderDrawRect(render, &man.shape);
            SDL_RenderCopy(render, texture, &texRect, &man.shape);
            SDL_RenderPresent(render);
            int64_t render_timer = (int64_t) roundf(1000.0f / (float)fps);
        }
        const int64_t end_frame_time = (int64_t) SDL_GetTicks();
        int64_t timer = delta_time - (end_frame_time - begin_frame_time);
        SDL_Delay((unsigned int) ((int64_t)10 > timer ? 10 : timer));
    }

    SDL_DestroyRenderer(render);
    SDL_DestroyWindow(gWindow);
    SDL_DestroyTexture(texture);
    IMG_Quit();
    SDL_Quit();

    return 0;
}




























/*
// 一段尘封的代码
#include <iostream>

class Box {
public:
    Box();
    Box(int T1 = 0, int T2 = 0, int T3 = 0);
    Box operator++();       //前置
    Box operator++(int);    //后置
private:
    int t1, t2, t3;
};

// 默认的构造函数
Box::Box() {}

// 构造函数，默认参数只需要写在声明中
Box::Box(int T1, int T2, int T3) {
    t1 = T1;
    t2 = T2;
    t3 = T3;
}

Box Box::operator++() {
    std::cout<< "Reload: " << ++t1 <<", "<< ++t2 << ", " << ++t3 << std::endl;
    return *this;
}

Box Box::operator++(int) {
    Box temp(*this);
    std::cout << "Reload: " << t1++ << ", " << t2++ << ", " << t3++ <<std::endl;
    return temp;
}

int main(int argc, char** argv) {
    Box box1 = Box(1, 2, 3);
    // or Box box1(1, 2, 3);
    Box box2 = ++box1;
    Box box3 = box1++;

    return 0;
}
*/